use crate::dto::*;
use crate::entity::*;
use crate::middleware::*;
use crate::RB;
use hypers::prelude::{hypers_openapi, openapi, OpenApi, Request, Responder, Response};
use log::error;
use rbatis::plugin::page::PageRequest;
use rbatis::rbdc::datetime::DateTime;
use rbs::to_value;
use std::collections::{HashMap, HashSet};
use hypers::serde_json::json;

pub struct User;

#[openapi(
    prefix = "/api",
    components(schemas(
        UserLoginReq,
        QueryUserRoleReq,
        UpdateUserRoleReq,
        UserListReq,
        UserSaveReq,
        UserUpdateReq,
        UserDeleteReq,
        UpdateUserPwdReq
    ))
)]
impl User {
    #[post("/login", tag = "后台用户登录",request_body = UserLoginReq)]
    async fn login(item: UserLoginReq) -> impl Responder {
        let user_result = SysUser::select_by_mobile(&mut RB.clone(), &item.mobile).await;
        match user_result {
            Ok(u) => match u {
                None => err_result_msg("用户不存在".to_owned()),
                Some(user) => {
                    let id = user.id.unwrap();
                    if user.password.ne(&item.password) {
                        return err_result_msg("密码不正确".to_owned());
                    }
                    let btn_menu = Self::query_btn_menu(&id).await;
                    if btn_menu.len() == 0 {
                        return err_result_msg("用户没有分配角色或者菜单,不能登录".to_owned());
                    }
                    match JWTToken::new(id, &user.user_name, btn_menu).create_token("123") {
                        Ok(token) => ok_result_data(token),
                        Err(err) => err_result_msg(err),
                    }
                }
            },
            Err(err) => {
                log::error!("select_by_column: {:?}", err);
                err_result_msg("查询用户异常".to_owned())
            }
        }
    }

    #[post("/query_user_role", tag = "查询用户角色",request_body = QueryUserRoleReq)]
    async fn query_user_role(item: QueryUserRoleReq) -> impl Responder {
        let user_role =
            SysUserRole::select_by_column(&mut RB.clone(), "user_id", item.user_id).await;
        let mut user_role_ids: Vec<i32> = Vec::new();
        for x in user_role.unwrap() {
            user_role_ids.push(x.role_id);
        }
        let sys_role = SysRole::select_all(&mut RB.clone()).await;

        let mut sys_role_list: Vec<UserRoleList> = Vec::new();

        for x in sys_role.unwrap() {
            sys_role_list.push(UserRoleList {
                id: x.id.unwrap(),
                status_id: x.status_id,
                sort: x.sort,
                role_name: x.role_name,
                remark: x.remark.unwrap_or_default(),
                create_time: x.create_time.unwrap().0.to_string(),
                update_time: x.update_time.unwrap().0.to_string(),
            });
        }
        ok_result_data(QueryUserRoleData {
            sys_role_list,
            user_role_ids,
        })
    }

    #[post("/update_user_role", tag = "更新用户与角色的关联",request_body = UpdateUserRoleReq)]
    async fn update_user_role(user_role: UpdateUserRoleReq) -> impl Responder {
        let role_ids = user_role.role_ids.clone();
        let len = user_role.role_ids.len();
        if user_role.user_id == 1 {
            return err_result_msg("不能修改超级管理员的角色");
        }
        let sys_result =
            SysUserRole::delete_by_column(&RB.clone(), "user_id", user_role.user_id).await;
        if sys_result.is_err() {
            return err_result_msg("更新用户角色异常");
        }
        let mut sys_role_user_list: Vec<SysUserRole> = Vec::new();
        for role_id in role_ids {
            sys_role_user_list.push(SysUserRole {
                id: None,
                create_time: Some(DateTime::now()),
                update_time: Some(DateTime::now()),
                status_id: 1,
                sort: 1,
                role_id,
                user_id: user_role.user_id,
            })
        }
        let result =
            SysUserRole::insert_batch(&mut RB.clone(), &sys_role_user_list, len as u64).await;
        handle_result(result)
    }

    #[get("/query_user_menu", tag = "查询用户菜单")]
    async fn query_user_menu(req: &mut Request) -> impl Responder {
        let user_id = req.get::<i32>("userId").unwrap();
        //let username = req.get::<String>("username").unwrap();
        //根据id查询用户
        let result = SysUser::select_by_id(&mut RB.clone(), user_id).await; //根据id查询用户
        // let mut res = Response::default();
        match result {
            Ok(sys_user) => {
                match sys_user {
                    // 用户不存在的情况
                    None => {
                        return json!(err_result_msg("用户不存在"));
                    }
                    Some(user) => {
                        //role_id为1是超级管理员--判断是不是超级管理员
                        let sql_str =
                            "select count(id) from sys_user_role where role_id = 1 and user_id = ?";
                        let count = RB
                            .query_decode::<i32>(sql_str, vec![to_value!(user.id)])
                            .await
                            .unwrap();

                        let sys_menu_list: Vec<SysMenu>;

                        if count > 0 {
                            sys_menu_list = SysMenu::select_all(&mut RB.clone())
                                .await
                                .unwrap_or_default();
                        } else {
                            let sql_str = "select u.* from sys_user_role t left join sys_role usr on t.role_id = usr.id left join sys_role_menu srm on usr.id = srm.role_id left join sys_menu u on srm.menu_id = u.id where t.user_id = ?";
                            sys_menu_list = RB
                                .query_decode(sql_str, vec![to_value!(user.id)])
                                .await
                                .unwrap();
                        }

                        let mut sys_menu: Vec<MenuUserList> = Vec::new();
                        let mut btn_menu: Vec<String> = Vec::new();
                        let mut sys_menu_ids: HashSet<i32> = HashSet::new();

                        for x in sys_menu_list {
                            if x.menu_type != 3 {
                                sys_menu_ids.insert(x.id.unwrap_or_default());
                                sys_menu_ids.insert(x.parent_id);
                            }
                            if x.api_url.clone().unwrap_or_default().len() > 0 {
                                btn_menu.push(x.api_url.unwrap_or_default());
                            }
                        }

                        let mut menu_ids = Vec::new();
                        for id in sys_menu_ids {
                            menu_ids.push(id)
                        }
                        let menu_result = SysMenu::select_by_ids(&mut RB.clone(), &menu_ids)
                            .await
                            .unwrap();
                        for menu in menu_result {
                            sys_menu.push(MenuUserList {
                                id: menu.id.unwrap(),
                                parent_id: menu.parent_id,
                                name: menu.menu_name,
                                icon: menu.menu_icon.unwrap_or_default(),
                                api_url: menu.api_url.clone().unwrap(),
                                menu_type: menu.menu_type,
                                path: menu.menu_url.unwrap_or_default(),
                            });

                            if menu.api_url.clone().unwrap_or_default().len() > 0 {
                                btn_menu.push(menu.api_url.unwrap_or_default());
                            }
                        }
                        let resp = ok_result_data(QueryUserMenuData {
                            sys_menu,
                            btn_menu,
                            avatar: "https://gw.alipayobjects.com/zos/antfincdn/XAosXuNZyF/BiazfanxmamNRoxxVxka.png".to_owned(),
                            name: user.user_name,
                        });
                        return json!(resp);
                    }
                }
            }
            // 查询用户数据库异常
            Err(err) => {
                log::error!("{}", err.to_string());
                return json!(err_result_msg(err.to_string()));
            }
        }
    }

    #[post("/user_list", tag = "查询用户列表", request_body = UserListReq)]
    async fn user_list(item: UserListReq) -> impl Responder {
        let mobile = item.mobile.as_deref().unwrap_or_default();
        //状态(1:正常，0:禁用),不传状态参数的时候,默认为2,在rbatis语句中判断
        let status_id = item.status_id.unwrap_or(2);
        let page_req = &PageRequest::new(item.page_no, item.page_size);
        let result =
            SysUser::select_page_by_name(&mut RB.clone(), page_req, mobile, status_id).await;
        let mut res: Response = Response::default();
        match result {
            Ok(page) => {
                let mut list_data: Vec<UserListData> = Vec::new();
                for user in page.records {
                    list_data.push(UserListData {
                        id: user.id.unwrap(),
                        sort: user.sort,
                        status_id: user.status_id,
                        mobile: user.mobile,
                        user_name: user.user_name,
                        remark: user.remark.unwrap_or_default(),
                        create_time: user.create_time.unwrap().0.to_string(),
                        update_time: user.update_time.unwrap().0.to_string(),
                    })
                }
                res.json(&ok_result_page(list_data, page.total));
                res
            }
            Err(err) => {
                error!("{}", err.to_string());
                res.json(&err_result_page(err.to_string()));
                res
            }
        }
    }
    #[post("/user_save", tag = "添加用户信息", request_body = UserSaveReq)]
    async fn user_save(user: UserSaveReq) -> impl Responder {
        log::info!("user_save params: {:?}", &user);
        let sys_user = SysUser {
            id: None,
            create_time: Some(DateTime::now()),
            update_time: Some(DateTime::now()),
            status_id: user.status_id,
            sort: user.sort,
            mobile: user.mobile,
            user_name: user.user_name,
            remark: user.remark,
            password: "123456".to_owned(), //默认密码为123456,暂时不加密
        };
        let result = SysUser::insert(&mut RB.clone(), &sys_user).await;
        handle_result(result)
    }

    #[post("/user_update", tag = "更新用户信息", request_body = UserUpdateReq)]
    async fn user_update(user: UserUpdateReq) -> impl Responder {
        log::info!("user_update params: {:?}", &user);
        let result = SysUser::select_by_id(&mut RB.clone(), user.id)
            .await
            .unwrap();

        match result {
            None => err_result_msg("用户不存在".to_string()),
            Some(sys_user) => {
                let sys_user = SysUser {
                    id: Some(user.id),
                    create_time: sys_user.create_time,
                    update_time: Some(DateTime::now()),
                    status_id: user.status_id,
                    sort: user.sort,
                    mobile: user.mobile,
                    user_name: user.user_name,
                    remark: user.remark,
                    password: sys_user.password,
                };
                let result = SysUser::update_by_column(&mut RB.clone(), &sys_user, "id").await;
                handle_result(result)
            }
        }
    }

    #[post("/user_delete", tag = "删除用户信息", request_body = UserDeleteReq)]
    pub async fn user_delete(item: UserDeleteReq) -> impl Responder {
        log::info!("user_delete params: {:?}", &item);
        for id in item.ids {
            if id != 1 {
                //id为1的用户为系统预留用户,不能删除
                let _ = SysUser::delete_by_column(&mut RB.clone(), "id", &id).await;
            }
        }
        ok_result_msg("删除用户信息成功".to_string())
    }

    #[post("/update_user_password", tag = "更新用户密码", request_body = UpdateUserPwdReq)]
    pub async fn update_user_password(user_pwd: UpdateUserPwdReq) -> impl Responder {
        log::info!("update_user_pwd params: {:?}", &user_pwd);
        let sys_user_result = SysUser::select_by_id(&mut RB.clone(), user_pwd.id).await;

        match sys_user_result {
            Ok(user_result) => match user_result {
                None => err_result_msg("用户不存在".to_string()),
                Some(mut user) => {
                    if user.password == user_pwd.pwd {
                        user.password = user_pwd.re_pwd;
                        let result = SysUser::update_by_column(&mut RB.clone(), &user, "id").await;
                        handle_result(result)
                    } else {
                        err_result_msg("旧密码不正确".to_string())
                    }
                }
            },
            Err(err) => {
                error!("{}", err.to_string());
                err_result_msg(err.to_string())
            }
        }
    }
}

impl User {
    async fn query_btn_menu(id: &i32) -> Vec<String> {
        let user_role = SysUserRole::is_admin(&mut RB.clone(), id).await;
        let mut btn_menu: Vec<String> = Vec::new();
        if user_role.unwrap().len() == 1 {
            let data = SysMenu::select_all(&mut RB.clone()).await;

            for x in data.unwrap() {
                btn_menu.push(x.api_url.unwrap_or_default());
            }
            log::info!("admin login: {:?}", id);
            btn_menu
        } else {
            let sql_str = "select distinct u.api_url from sys_user_role t left join sys_role usr on t.role_id = usr.id left join sys_role_menu srm on usr.id = srm.role_id left join sys_menu u on srm.menu_id = u.id where t.user_id = ?";
            let btn_menu_map = RB
                .query_decode::<Vec<HashMap<String, String>>>(sql_str, vec![to_value!(id)])
                .await
                .unwrap();
            for x in btn_menu_map {
                btn_menu.push(x.get("api_url").unwrap().to_string());
            }
            log::info!("ordinary login: {:?}", id);
            btn_menu
        }
    }
}
